Interaktivní grafy s Google Charts

2 JavaScript, Google, HTML, CSS

Google nabízí velké množství služeb, včetně grafů, a to i přizpůsobitelných a interaktivních. Aktuálně paleta nabízí 29 druhů grafů od základních sloupcových či koláčových až po Sankeyho diagramy nebo GEO grafy.

Interaktivní grafy s Google Charts

Ukázka všech možností, co grafy nabízí, by bylo na desítky stran, možná i více. Výhodou ale je, že formát dat je pro většinu grafů téměř totožný, a poté se pouze mění volání jednotlivých grafů. Proto zde jsou ukázány základy, které ve většině případů stačí, a odkazy na detailnější dokumentaci.

Pokud vás zajímá jen ukázka, je na testdata.kutac.cz. Pro bližší info a přiblížení čtěte dále.

Načtení, lokalizace a DataTable

Grafy jsou vykreslovány přímo v prohlížeči pomocí SVG, případně VML pro starší verze Internet Exploreru. Na začátku se načte skript od Google, který je potřeba inicializovat a lokalizovat. Lokalizace nutná není, ale velmi se hodí pro správné formáty čísel a datumů v grafu. Lze také přidat Google Map API klíč pro mapové grafy apod., viz dokumentace. Výhodou oproti jiným službám od Google je, že není potřeba žádná registrace v Google Consoli, protože se vše děje v prohlížeči návštěvníka. API klíč je nutný až v případě propojení s Google Mapami, tabulkami a jinými službami.

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
  google.charts.load('current', {'packages':['corechart'], 'language': 'cs'});
  google.charts.setOnLoadCallback(drawCharts);
</script>

Žádný graf nepůjde vykreslit bez dat a ty musejí být převedeny do DataTable. Nemá smysl se snažit tuto část nějak urychlit či přeskočit, je to zbytečné, osobní zkušenost. Obrovskou výhodou DataTable je kromě jednotného formátu dat pro všechny typy grafů také možnost načítat z Datasource Query. Ten například podporují Google Spreadsheets, Fusion Tables případně lze implementovat i do své služby.

Kromě dat se v DataTable dají specifikovat i formáty a chování dat, filtrace, seřazení a mnohé další. Je tak možné naformátovat cenu, datum, čas i čísla, dodat hodnoty do tooltipu a tak dále. Vytvoření tabulky a určení datového typu, role a formátu hodnot je trochu komplikovanější, doporučuji pročíst odkazy na dokumentaci rolí a vytváření sloupců. Pro správnou funkci je nutné, aby datum a čas se před vložením do DataTable převedly na JS Date() objekt.

Všechny možnosti nastavení grafů jsou velmi rozsáhlé, proto i ta část mnou použita je podrobněji pospána až na ukázkách k jednotlivým grafům. Všechny funkce a metody jsou popsány v dokumentaci, dle mě trochu nepřehledně, na jedné stránce. Pro většinu běžného použití ale vystačí praktické ukázky níže, nebo přímo na webu Google Charts.

Praktická ukázka

Následující grafy ukazují prodeje lístků na portálu tickito.cz. Údaje jsou smyšlené, ale grafy jsou vykreslovány úplně stejně. Po apelaci přednášející na VŠ jsem se vyhnul koláčovým grafům, jsou zlo, ale to je na jiné téma. Grafy obsahují různé formátování dat na osách a v tooltipu, vícero vertikálních os v jednom grafu a další.

Kód je dosti dlouhý, proto je možné jej stáhnout jako HTML soubor, spustit na testdata.kutac.cz, nebo si jej zde rychle pročíst.

// ================== chart_daySales ========================
var chartData = new google.visualization.DataTable();
// První sloupec je vždy v roli domény (hodnota na ose X)
chartData.addColumn('date', 'Datum');
// Další sloupce jsou datové
chartData.addColumn('number', 'Objednávky');
chartData.addColumn('number', 'Lístky');
chartData.addColumn('number', 'Cena');
// Sloupec v roli tooltipu, obsahuje to, co se zobrazí při najetí
// vztahuje se vždy pouze k předešlému sloupci
chartData.addColumn({role: 'tooltip', type: 'string'});
// Vložení všech dat pomocí 1 velkého pole
chartData.addRows([
    [new Date("2017-05-15"), 1,  3,   450,   "450 Kč"],
    [new Date("2017-05-16"), 14, 22, 2970, "2 970 Kč"],
    [new Date("2017-05-17"), 8,  12, 1320, "1 320 Kč"],
    [new Date("2017-05-18"), 12, 20, 2800, "2 800 Kč"],
    [new Date("2017-05-19"), 16, 23, 2645, "2 645 Kč"],
    [new Date("2017-05-20"), 6,  14, 1820, "1 820 Kč"],
    [new Date("2017-05-21"), 9,  15, 1970, "1 970 Kč"],
    [new Date("2017-05-22"), 3,  6,   840,   "840 Kč"],
    [new Date("2017-05-23"), 9,  17, 2295, "2 295 Kč"],
    [new Date("2017-05-24"), 12, 25, 3475, "3 475 Kč"],
    [new Date("2017-05-25"), 28, 48, 6240, "6 240 Kč"],
    [new Date("2017-05-26"), 42, 76, 9880, "9 880 Kč"]
]);
var options = {
    title: 'Denní prodeje', // Titulek grafu
    titleTextStyle: { fontSize: 24 },
    width: 1000,
    height: 500,
    // Při najetí vybere všechny data na dané X-ové hodnotě
    // v tooltipu také zobrazí všechny 3 hodnoty dohromady
    focusTarget: 'category',
    // Graf obsahuje 3 sloupce hodnot (série), a pro 3. sérii
    // (tj 2. - číslováno je od 0) bude osa s indexem 1 (tj 2.)
    series: {
        2: { targetAxisIndex: 1 }
    },
    // Nastavení jednotlivých vertikálních os
    vAxes: {
        0: { title: 'Počet'},
        1: { title: 'Cena', format: '# Kč' }
    }
};
var chart_daySales = new google.visualization.LineChart(document.getElementById('chart_daySales'));
chart_daySales.draw(chartData, options);

// ================== chart_categorySales ========================
chartData = new google.visualization.DataTable();
// Styl tvorby stále shodný s předchozím grafem
chartData.addColumn('string', 'Kategorie');
chartData.addColumn('number', 'Dospělý');
chartData.addColumn('number', 'Dětský');
chartData.addColumn('number', 'Důchodce');

// Jiná možnost vložení hodnot, po jednotlivých záznamech
chartData.addRow(['Hlavní sál', 85, 36, 29]);
chartData.addRow(['Vedlejší sál', 61, 12, 27]);
chartData.addRow(['Balkón', 15, 5, 11]);

var options = {
    title: 'Prodeje v kategoriích',
    titleTextStyle: { fontSize: 24 },
    width: 1000,
    height: 500,
    // Pouze 1 vertikální osa, není potřeba indexu jako minule
    vAxis: { title: 'Počet'},
    // Jednotlivé série nebudou ve zvláštních sloupcíh, ale na sobě
    isStacked: true,
    legend: { position: 'top' },
};
var chart_categorySales = new google.visualization.ColumnChart(document.getElementById('chart_categorySales'));
chart_categorySales.draw(chartData, options);

// ================== chart_hourSales ========================

// Jiná možnost určení tabulky, první pole určuje vždy typy a názvy sloupců
// Hodnota domény obsahuje formátování, které se zobrazuje v tooltipu
chartData = new google.visualization.arrayToDataTable([
    ['Hodina', 'Objednávky', 'Lístky'],
    [{v:  0, f: "00:00 - 00:59"},  2,  4],
    [{v:  1, f: "01:00 - 01:59"},  1,  2],
    [{v:  2, f: "02:00 - 02:59"},  0,  0],
    [{v:  3, f: "03:00 - 03:59"},  0,  0],
    [{v:  4, f: "04:00 - 04:59"},  2,  4],
    [{v:  5, f: "05:00 - 05:59"},  5,  9],
    [{v:  6, f: "06:00 - 06:59"},  7, 12],
    [{v:  7, f: "07:00 - 07:59"},  9, 16],
    [{v:  8, f: "08:00 - 08:59"},  6,  9],
    [{v:  9, f: "09:00 - 09:59"},  8, 12],
    [{v: 10, f: "10:00 - 10:59"},  4,  8],
    [{v: 11, f: "11:00 - 11:59"},  3,  6],
    [{v: 12, f: "12:00 - 12:59"},  2,  4],
    [{v: 13, f: "13:00 - 13:59"},  4,  8],
    [{v: 14, f: "14:00 - 14:59"},  9, 17],
    [{v: 15, f: "15:00 - 15:59"}, 10, 19],
    [{v: 16, f: "16:00 - 16:59"},  8, 14],
    [{v: 17, f: "17:00 - 17:59"}, 11, 18],
    [{v: 18, f: "18:00 - 18:59"},  9, 15],
    [{v: 19, f: "19:00 - 19:59"},  9, 14],
    [{v: 20, f: "20:00 - 20:59"}, 14, 23],
    [{v: 21, f: "21:00 - 21:59"}, 17, 32],
    [{v: 22, f: "22:00 - 22:59"}, 16, 27],
    [{v: 23, f: "23:00 - 23:59"},  4,  8],
]);        
var options = {
    title: 'Prodeje podle hodin',
    titleTextStyle: { fontSize: 24 },
    width: 1000,
    height: 500,
    // Shodné jako v prvním grafu, seskupení všech sérií při výběru
    focusTarget: 'category',
    // Nastavení jednotlivých os
    vAxis: { title: 'Počet' },
    hAxis: { title: 'Hodina' },
    // Přebarvení jednotlivých sérii
    series: {
        0: {color: 'orange'},
        1: {color: 'purple'},
    }
};
var chart_hourSales = new google.visualization.ColumnChart(document.getElementById('chart_hourSales'));
chart_hourSales.draw(chartData, options);

Případné zkušenosti s knihovou pro vykreslování grafů od Google, nebo i někoho jiného, můžete sdílet v komentářích.

K tomuto článku již není možné přidávat další komentáře

Komentáře

Perfektní ukázka se srozumitelným kometářem kódu, ušetřil jste mi hodně práce.
Díky Milan

Díky za komentář. Jsem vždy rád, když můj článek někomu pomůže. Alespoň vím, že je nepíšu nadarmo